package com.tuo51.evaluate.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.commons.exception.BusinessException;
import com.matt.domain.Children;
import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.query.EvaluateQuery;
import com.matt.commons.page.PagerQuery;
import com.matt.repository.ChildrenRepository;
import com.matt.repository.FeedsRepository;
import com.matt.service.ChildrenService;
import com.matt.service.WxPushService;
import com.tuo51.components.redis.RedisService;
import com.tuo51.core.domain.org.Organization;
import com.tuo51.core.repositories.OrgnizationRepository;
import com.tuo51.evaluate.domain.evaluatingV2.*;
import com.tuo51.evaluate.repositories.evaluatev2.*;
import com.tuo51.evaluate.service.EvaluateV2ConclusionService;
import com.tuo51.evaluate.service.EvaluateV2Service;
import com.tuo51.evaluate.vo.evaluate.*;
import com.tuo51.foudation.constant.EvaluatingConstant;
import com.tuo51.foudation.utils.CopyUtils;
import com.tuo51.foudation.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.matt.foundation.model.ErrorCode.EVALUATE_RECORD_NOT_EXIST;
import static com.tuo51.evaluate.service.impl.EvaluateV2ExportServiceImpl.SkipDimensionID;

@Service
@Slf4j
@CacheConfig(cacheNames = "EvaluateV2ServiceImpl")
public class EvaluateV2ServiceImpl implements EvaluateV2Service {


//    @Autowired
//    private EvaluateStaffService evaluateStaffService;

    @Autowired
    private WxPushService pushService;

    @Autowired
    private ChildrenRepository childrenRepository;

    @Autowired
    private ChildrenService childrenService;

    @Autowired
    private FeedsRepository feedsRepository;

    @Autowired
    private EvaluateV2RecordRepository recordRepository;

    @Autowired
    private EvaluateV2QuestionRepository questionRepository;

    @Autowired
    private EvaluateNativeRepository nativeRepository;

    @Autowired
    private EvaluateV2DimensionRepository dimensionRepository;

    @Autowired
    private EvaluateV2RecordAnswerRepository answerRepository;

    @Autowired
    private EvaluateV2ItemRepository itemRepository;

    @Autowired
    private EvaluateV2ToolRepository toolRepository;

    @Autowired
    private EvaluateV2ToolNativeRepository toolNativeRepository;

    @Autowired
    private EvaluateV2RecordDimensionScoreRepository dimensionScoreRepository;

    @Autowired
    private EvaluateV2ConclusionService conclusionService;

    @Autowired
    private EvaluateV2DimensionRecommendTipsRepository tipsRepository;

    @Autowired
    private OrgnizationRepository orgnizationRepository;


    @Autowired
    private RedisService redisService;

    @Override
    public Page findEvaluatesByTeacherId(String teacherId, String areaId, PagerQuery pagerQuery) {

        Pageable pageRequest = PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize());

        return recordRepository.findAllByCreateTeacherIdAndFinishedAndDeleted(teacherId, true, false, pageRequest);
    }

    @Override
    public Page findEvaluatesByTeacherId(String teacherId, PagerQuery pagerQuery) {
        Pageable pageRequest = PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize());

        return recordRepository.findAllByCreateTeacherIdAndFinishedAndDeleted(teacherId, true, false, pageRequest);
    }

    private List<EvaluateChildrenVO> attachEvaluateSummary(List<Children> childrenList){
        List<EvaluateChildrenVO> voList = Lists.newArrayList();

        childrenList.forEach(o -> {
            voList.add(EvaluateChildrenVO.of(o));
        });

        return voList;
    }

    @Override
    public List<EvaluateChildrenVO> getChildrenEvaluateInfo(String staffId, String orderBy) {
        if (orderBy == null){
            orderBy = "";
        }

        List<Children> childrenList = null;
        switch (orderBy){
            default:{
                childrenList = childrenRepository.findByStaffIdAndDeletedIsFalseOrderByCreatedDesc(staffId);
            }break;
            case ORDERBY_NEXT:{
                childrenList = childrenRepository.findByStaffIdAndDeletedIsFalseOrderByNextEvaluateDateDesc(staffId);
            }break;
            case ORDERBY_LAST:{
                childrenList = childrenRepository.findByStaffIdAndDeletedIsFalseOrderByLastEvaluateDateDesc(staffId);
            }break;

            case ORDERBY_BIRTHDAY:{
                childrenList = childrenRepository.findByStaffIdAndDeletedIsFalseOrderByBirthdayDesc(staffId);
            }break;
        }

        List<EvaluateChildrenVO> voList = attachEvaluateSummary(childrenList);

        return voList;
    }

    @Override
    public List<EvaluateChildrenVO> getChildrenByNameEvaluate(String staffId, String name, String orderBy) {
        List<Children> childrenList = null;
        if (orderBy == null){
            orderBy = "";
        }
        switch (orderBy){
            default:{
                childrenList = childrenRepository.findByStaffIdAndNameLikeAndDeletedIsFalseOrderByCreatedDesc(staffId, name);
            }break;
            case ORDERBY_NEXT:{
                childrenList = childrenRepository.findByStaffIdAndNameLikeAndDeletedIsFalseOrderByNextEvaluateDateDesc(staffId, name);
            }break;
            case ORDERBY_LAST:{
                childrenList = childrenRepository.findByStaffIdAndNameLikeAndDeletedIsFalseOrderByLastEvaluateDateDesc(staffId, name);
            }break;

            case ORDERBY_BIRTHDAY:{
                childrenList = childrenRepository.findByStaffIdAndNameLikeAndDeletedIsFalseOrderByBirthdayDesc(staffId, name);
            }break;
        }

        List<EvaluateChildrenVO> voList = attachEvaluateSummary(childrenList);

        return voList;
    }

    @Override
    public List<EvaluateV2Record> getEvaluateRecordByChildrenId(String childrenId) {
        List<EvaluateV2Record> recordList = recordRepository.findAllByChildrenIdAndDeletedIsFalseAndFinishedIsTrueOrderByCreated(childrenId);
        return recordList;
    }

    @Override
    public Page<WebEvaluateRecordListVo> getEvaluatePage(EvaluateQuery query) {

        List<String> cs = null;


        final  List<String> childrenIds = cs;

        Specification<EvaluateV2Record> specification = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("areaId"), query.getAreaId() )));

            if (StringUtils.isNotBlank(query.getChildrenId())) {
                predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("childrenId"), query.getChildrenId())));
            }else if(childrenIds != null && childrenIds.size() > 0){
                CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("childrenId").as(String.class));
                for (String id : childrenIds){
                    in.value(id);
                }
                predicates.add(criteriaBuilder.and(in));
            }

            if (StringUtils.isNotBlank(query.getChildrenName()))
                predicates.add(criteriaBuilder.and(criteriaBuilder.like(root.get("childrenName"), "%" + query.getChildrenName() + "%")));

            if (StringUtils.isNotBlank(query.getStaffId())) {
                predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("createTeacherId"), query.getStaffId())));
            }

            if (Objects.nonNull(query.getMonth()))
                predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("month"), query.getMonth())));

            if (Objects.nonNull(query.getOrderStatus()))
                predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("category"), query.getOrderStatus())));

            if (Objects.nonNull(query.getStatus())) {
                predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("status"), query.getStatus())));
            }

            predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("finished"), true)));
            predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("deleted"), false)));

            if (query.getCreateTimeQuery() != null && query.getCreateTimeQuery().size() >= 2) {
                String startTimeStr = query.getCreateTimeQuery().get(0);
                String endTimeStr = query.getCreateTimeQuery().get(1);

                // 时间格式转换（示例采用yyyy-MM-dd格式）
                LocalDateTime startTime = LocalDateTime.parse(startTimeStr + "T00:00:00");
                LocalDateTime endTime = LocalDateTime.parse(endTimeStr + "T23:59:59");

                predicates.add(criteriaBuilder.between(root.get("created"), startTime, endTime));
            }

            criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));

            if(StringUtils.isNotBlank(query.getOrderBy())){
                if(StringUtils.isBlank(query.getSequence()) || "asc".equalsIgnoreCase(query.getSequence())){
                    criteriaQuery.orderBy(criteriaBuilder.asc(root.get(query.getOrderBy())));
                }else{
                    criteriaQuery.orderBy(criteriaBuilder.desc(root.get(query.getOrderBy())));
                }
            }else {
                criteriaQuery.orderBy(criteriaBuilder.desc(root.get("created")));
            }


            return criteriaQuery.getRestriction();
        };
        Pageable pageable = PageRequest.of(query.getPageNum(), query.getPageSize());
        Page<EvaluateV2Record> page = recordRepository.findAll(specification, pageable);
        List<WebEvaluateRecordListVo> voList = page.getContent().stream().map(o -> WebEvaluateRecordListVo.of(o)).collect(Collectors.toList());
        return new PageImpl<WebEvaluateRecordListVo>(voList, pageable, page.getTotalElements());
    }


    @Transactional
    @Override
    public Map submitAdvise(StaffDTO staff, String evaluateRecordId, String advise, Integer infoType, String infoDomainId, String height, String weight, String header) {
        EvaluateV2Record record = recordRepository.getOne(evaluateRecordId);

        if(record == null){
            throw new BusinessException(EVALUATE_RECORD_NOT_EXIST, "不存在的测评记录");
        }

        //
        if(infoType != null) {
            record.setHealthInfoFromType(infoType);
        }
        if(weight != null) {
            record.setWeight(weight);
        }
        if(header != null) {
            record.setHeader(header);
        }
        if(height != null) {
            record.setHeight(height);
        }

        if(infoDomainId != null) {
            record.setHealthInfoFromDomainId(infoDomainId);
        }

        record.setStatus(EvaluatingConstant.EvaluateRecordStatus.ASSESS.codeOf());
        record.setAdvise(advise);

        record.setEvaluatingTeacherId(staff.getId());
        record.setEvaluatingTeacherName(staff.getRealName());

        EvaluateV2Record save = recordRepository.save(record);

        return CopyUtils.transBean2Map(save);
    }

    @Transactional
    @Override
    public EvaluateV2Record modifyEvaluateRecord(String evaluateRecordId, String height, String weight, String header, String staffId, String staffName) {
        EvaluateV2Record record = recordRepository.getOne(evaluateRecordId);
        record.setHeight(height);
        record.setWeight(weight);
        record.setHeader(header);
        record.setEvaluatingTeacherId(staffId);
        record.setEvaluatingTeacherName(staffName);
        return record;
    }

    @Transactional
    @Override
    public EvaluateV2Record modifyEvaluateAdvise(String evaluateRecordId, String advise, String staffId, String staffName) {
        EvaluateV2Record record = recordRepository.getOne(evaluateRecordId);
        record.setAdvise(advise);
        record.setEvaluatingTeacherId(staffId);
        record.setEvaluatingTeacherName(staffName);
        return record;
    }

    @Transactional(rollbackFor = BusinessException.class)
    public EvaluateV2Record finishEvaluateWithTimes(String evaluateRecordId, Organization org){
        EvaluateV2Record ret = finishEvaluate(evaluateRecordId, true);

        org.setRestCount(org.getRestCount() - 1);
        if (org.getRestCount() < 0){
            throw new BusinessException(ErrorCode.VIP_NEEDED, "可用报告查阅次数不够");
        }
        orgnizationRepository.save(org);

        return ret;
    }

    @Transactional
    @Override
    public EvaluateV2Record finishEvaluate(String evaluateRecordId, boolean paid) {
        EvaluateV2Record record = recordRepository.getOne(evaluateRecordId);

        record.setFinished(true);
        record.setPublished(true);
        record.setPaid(paid);

        //计算最后评级
        List<EvaluateV2RecordDimensionScore> dimensionScores = dimensionScoreRepository.findAllByRecordIdOrderByCreated(record.getId());
        int dq = 0;   //计算发育商
        int skipped = 0;
        for(int i = 0 ; i < dimensionScores.size(); i++){
            EvaluateV2RecordDimensionScore c = dimensionScores.get(i);

            if(c.getDimensionId().equals(SkipDimensionID)) {
                skipped = 1;
            }else{
                dq += c.getDq();
            }
        }

        //计算总用时间
        Long duration = nativeRepository.fullEvaluateDurationForRecord(record.getId());
        record.setDuration(duration);

        //
        dq = dq / (dimensionScores.size() -  skipped);
        record.setRating(conclusionService.dqRating ( dq / 10 ));
        record.setDq(dq);

        //
        recordRepository.save(record);

        //更新宝宝信息
        Children c = childrenRepository.getOne(record.getChildrenId());
        c.setWeight(record.getWeight());
        c.setHeight(record.getHeight());
        c.setHeader(record.getHeader());

        // TODO
//        c.setLastEvaluateDate(new Date());
//        c.setNextEvaluateDate( EvaluationReportUtils.nextEvaluateDate(record.getEvaluatingDate(), record.getMonth()));

        childrenRepository.save(c);

        //删除报告的缓存
        redisService.deleteLike(record.getId());

        return record;
    }

    @Override
    public EvaluateV2Record payEvaluate(String evaluateRecordId){
        EvaluateV2Record record = recordRepository.getOne(evaluateRecordId);
        if (record.getPaid()){
            throw new BusinessException(ErrorCode.OPERATION_DUPLICATED, "已经支付过了。");
        }

        record.setPaid(true);
        recordRepository.save(record);

        return record;
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public EvaluateV2Record payEvaluateWithTimes(String evaluateRecordId, Organization org){
        EvaluateV2Record record = payEvaluate(evaluateRecordId);

        org.setRestCount(org.getRestCount() - 1);
        if (org.getRestCount() < 0){
            throw new BusinessException(ErrorCode.VIP_NEEDED, "可用报告查阅次数不够");
        }
        orgnizationRepository.save(org);

        return record;
    }

    @Override
    public List<EvaluateV2Question> failedQuestion(String childrenId, String evaluateRecordId) {
        return questionRepository.findAllFailedQuestion(evaluateRecordId);
    }

    @Override
    public EvaluateV2Record startEvaluate(StaffDTO staff, String evaluateId, String weight, String height, boolean skipWarningDiemension){
        EvaluateV2Record record = recordRepository.getOne(evaluateId);

        record.setWeight(weight);
        record.setHeight(height);

        if(skipWarningDiemension){
            record.setSkipDiemnsions(WARNING_DIMENSION_ID);
        }

        recordRepository.save(record);

        return record;
    }

    @Override
    @Transactional
    public EvaluateV2Record createEvaluate(String evaluateType, StaffDTO staff, Children c, String weight, String height, List<EvaluateV2SheetAnswerPO> answers, List<String> skipDiemnsions, Long duration ){
        //先把答案转成map
        Map <String, Boolean> checkSheet = answers.stream().collect(Collectors.toMap(EvaluateV2SheetAnswerPO::getQid, EvaluateV2SheetAnswerPO::getChecked));

        //然后开始轮询，获取所有的items
        List<EvaluateV2Item> items = itemRepository.findAllByOrderByDimensionCodeAscMonthAsc();;

        List<EvaluateV2Question> fullQuestions = questionRepository.findAll();
        Map<String, List<EvaluateV2Question>> questionCache = new HashMap<>();
        for (EvaluateV2Question question : fullQuestions){
            List<EvaluateV2Question> itemQuestions = questionCache.get(question.getItemId());
            if (itemQuestions == null){
                itemQuestions = new ArrayList<>(2);
                questionCache.put(question.getItemId(), itemQuestions);
            }
            itemQuestions.add(question);
        }

        //所有的维度
        List<EvaluateV2Dimension> dimensions = dimensionRepository.findAllByDeletedOrderByCode(false);
        Map<String, EvaluateV2Dimension> dimensionCache = dimensions.stream().collect(Collectors.toMap(EvaluateV2Dimension::getId, o -> o));
        Set<String> skiping = null;
        if (skipDiemnsions != null && skipDiemnsions.size() > 0){
            skiping = skipDiemnsions.stream().collect(Collectors.toSet());
        }else {
            skiping = new HashSet();
        }

        //最后得分
        Map<String, EvaluateV2RecordDimensionScore> scores = new HashMap<>();

        //创建报告
        EvaluateV2Record record = startEvaluate(staff, c, weight, height, false, 0);

        //宝宝月龄
        double actualMonth = DateUtil.betweenMonthsV2(record.getEvaluatingDate(), record.getBirthday());

        //然后开始轮询，计算得分
        String shortId = null;    // 短路能区
        String dimensionParsed = null;   //
        int unpassCount = 0;

        List<EvaluateV2RecordAnswer> answerObjsToSave = new ArrayList<>();
        for (EvaluateV2Item item : items){

            EvaluateV2Dimension dimension = dimensionCache.get(item.getDimensionId());
            EvaluateV2RecordDimensionScore score = scores.get(item.getDimensionId());

            if (item.getDimensionId().equals(shortId)){   //短路能区
                continue;
            }
            if (!item.getDimensionId().equals(dimensionParsed)){
                dimensionParsed = null;
            }

            List<EvaluateV2Question> questions = questionCache.get(item.getId());

            //问题得分
            double ppq =(item.getScore()+ 0.0) / (item.getQuestionCount() + 0.0) * 10;
            int pointPerQuestion = (int)ppq;

            //检查是不是所有都通过
            boolean anyChecked = false;

            for (EvaluateV2Question q : questions){
                Boolean checked = checkSheet.get(q.getId());

                if (checked == null){
                    if (dimensionParsed != null){
                        //开始计算能区时若遇上题空白，则直接判不通过
                        checked = false;
                    }else {
                        continue;
                    }
                }

                //问题状态
                anyChecked |= checked;

                if ( dimensionParsed == null) {
                    //第一格答案
                    if (checked == false) {
                        //第一格并不是完全通过
                        log.warn("got first item not fully passed " + dimension.getName() + "  " + item.getMonth() + "q:" + questions);
                    }
                    // 能区得分对象
                    if (score == null) {
                        score = scoreForDimensionAndBaseItem(record.getId(), dimension, item, actualMonth);
                        scores.put(item.getDimensionId(), score);
                    }
                }

                //标记
                if (!item.getDimensionId().equals(dimensionParsed)){
                    //能区变更，置零,跳过所有问题
                    shortId = null;
                    dimensionParsed = item.getDimensionId();
                    unpassCount = 0;
                }

                //创建答案
                EvaluateV2RecordAnswer answer = EvaluateV2RecordAnswer.of(q.getId(), c.getId(), record.getId(),
                        score.getId(), item.getMonth(), q.getTitle(), checked, checked ? pointPerQuestion : 0);
                answerObjsToSave.add(answer);

                //计算维度得分
                score.setScore(score.getScore() + answer.getScore());
                //新的得分计算
                score.setMonth(score.getMonth() + answer.getScore());
                //计算发育商
                score.setDq((int)(score.getMonth() * 1.0 / actualMonth * 100 /*100%*/));
            }

            if (anyChecked){
                unpassCount = 0; //重置计数器
            } else if (dimensionParsed != null){  //不通过
                unpassCount += 1;  //增加不通过单元计数器
            }

            if (unpassCount >= 2){ //连续两个
                //短路这个维度后面所有单元
                shortId = item.getDimensionId();
                unpassCount = 0;
            }
        }

        {
            //TODO: 确保所有能区都有score对象
        }

        {        //找到交流互动警示行为， 并更新计算方式
            EvaluateV2RecordDimensionScore score = scores.get(WARNING_DIMENSION_ID);
            if (score == null) {
                EvaluateV2Dimension dimension = dimensionCache.get(WARNING_DIMENSION_ID);
                score = EvaluateV2RecordDimensionScore.of(record.getId(), dimension.getId(),dimension.getName(), 0, null, false);
                scores.put(WARNING_DIMENSION_ID, score);
            }
            resetWarningDimensionScore(score, actualMonth);
        }

        //保存所有答案
        answerRepository.saveAll(answerObjsToSave);

        //保存得分
        dimensionScoreRepository.saveAll(scores.values());

        //保存 record 完成状态
        //计算得分
        try {
            record = finishEvaluate(record.getId(), true);
        }catch (Exception e){
            e.printStackTrace();

            throw new BusinessException(ErrorCode.PARAM_CAN_NOT_BLANK, "无法创建报告，请检查答案列表");
        }
        {//修正测评时间
            EvaluateV2Record r = recordRepository.getOne(record.getId());
            r.setDuration(duration);
            r.setEvaluateType(evaluateType);
            recordRepository.save(r);
        }

        //保存record
        return record;
    }

    @Override
    public EvaluateV2Record startEvaluate(StaffDTO staff, Children c, String weight, String height, boolean skipWarningDiemension, Integer demo) {

//        StaffDTO staff = evaluateStaffService.getById(teacherId);

        EvaluateV2Record record = new EvaluateV2Record();

        if(skipWarningDiemension){
            record.setSkipDiemnsions(WARNING_DIMENSION_ID);
        }

        record.setDemoType(demo);
        record.setCreateTeacherId(staff.getId());
        record.setCreateTeacherName(staff.getRealName());

        record.setEvaluatingDate(new Date());
        record.setEvaluatingTeacherId(staff.getId());
        record.setEvaluatingTeacherName(staff.getRealName());

        record.setAreaId(c.getAreaId());
        record.setChildrenId(c.getId());
        record.setChildrenName(c.getName());
        record.setChildrenNickName(c.getNickName());

        record.setBirthday(c.getBirthday());
        record.setGender(c.getGender());
        record.setCategory(2);

        record.setWeight(weight);
        record.setHeight(height);

        record.setMonth(DateUtil.betweenMonths(new Date(), c.getBirthday()));

        recordRepository.save(record);

        return record;
    }

    boolean allFalse(boolean[] checkeds){
        for (boolean b : checkeds){
            if(b){
                return false;
            }
        }
        return true;
    }

    private EvaluateV2Item defaultItem(String dimensionId, double actualMonth, Integer demo){
        int month = (int)actualMonth;

        //找到前两个item
        List<EvaluateV2Item> items = itemRepository.findTop2ByDimensionIdAndMonthLessThanAndDeletedOrderByMonthDesc(dimensionId, month, false);

        EvaluateV2Item evaluateItem = null;
        if(items.size() > 0){
            if (demo == 1){
                evaluateItem =  items.get(0);
            }else {
                evaluateItem = items.get(items.size() - 1);
            }
        }else{
            //缺省
            evaluateItem = itemRepository.findFirstByDimensionIdAndDeletedOrderByMonth(dimensionId, false);
        }
        return evaluateItem;
    }

    private EvaluateV2RecordDimensionScore defaultDimensionScore(String recordId, EvaluateV2Item evaluateItem, EvaluateV2Dimension dimension, double actualMonth ){
        EvaluateV2RecordDimensionScore dimensionScore = dimensionScoreRepository.findOneByRecordIdAndDimensionId(recordId, dimension.getId());
        if(dimensionScore == null) {
            dimensionScore = scoreForDimensionAndBaseItem(recordId, dimension, evaluateItem, actualMonth);
            dimensionScoreRepository.save(dimensionScore);
        }
        return  dimensionScore;
    }

    private EvaluateV2RecordDimensionScore scoreForDimensionAndBaseItem(String recordId, EvaluateV2Dimension dimension, EvaluateV2Item item, double actualMonth){
        int defaultScore = (item == null) ? 0 : (item.getMonth() - item.getScore()) * 10;
        if(dimension.getDefaultValueType() == 1){
            defaultScore = 0;
        }
        EvaluateV2RecordDimensionScore score = EvaluateV2RecordDimensionScore.of(recordId, dimension.getId(), dimension.getName(), defaultScore, null, false);

        //基础月龄
        score.setMonth(defaultScore);

        //基础发育商
        score.setDq((int)(defaultScore * 1.0 / actualMonth * 100 /*100%*/));

        return score;
    }

    @Override
    public EvaluateV2Record draftEvaluateItemLastNotFinished(String teacherId, String childrenId, String childrenName){
        EvaluateV2Record record = null;

        if(StringUtils.isBlank(childrenId)){
            record = recordRepository.findLatestUnfinishedReportByChildrenName(childrenName, teacherId);
        }else{
            Children c = childrenRepository.getOne(childrenId);

            if(c == null){
                throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在");
            }

            //月龄
            Integer month = DateUtil.betweenMonths(new Date(), c.getBirthday());

            //
            record = recordRepository.findLatestUnfinishedReportByChildrenId(childrenId, month, teacherId);
        }

        if (record != null && record.getFinished()){
            record = null;
        }

        return record;
    }

    @Override
    public Map cacheAnswerForEvaluateItem(String recordId, String options){
        Map cache = new HashMap();
        if(StringUtils.isEmpty(options)){
            return cache;
        }

        //当期缓存
        //处理options，并写redis
//        JSONArray items = JSON.parseArray(options);
        JSONObject items = JSON.parseObject(options);

        if(items.size() > 0){
            Set<Map.Entry<String, Object>> entries = items.entrySet();

            for(Map.Entry<String,Object> entry : entries){

                String id = entry.getKey();
                String checked = entry.getValue().toString();
                cache.put(id, checked);

                redisService.saveValue(recordId + id, checked);
            }
        }

        return cache;
    }

    @Override
    public void markShortItemsUnpassed(String recordId, EvaluateV2Question question){
        while (question.getShortIndex() != null && question.getShortIndex() > question.getIndexOnPaper()){
            question = questionRepository.getByIndexOnPaperAndDeletedIsFalse(question.getShortIndex());
            String key = recordId + question.getId();
            redisService.saveValue(key, "false");
        }
    }

    @Override
    public boolean anyQuestionInItemNotChecked(String recordId, EvaluateV2Item item){
        boolean anyNotChecked = false;

        for (EvaluateV2Question question : item.getQuestions()){
            String key = recordId + question.getId();
            String checked = redisService.getValue(key);
            if(StringUtils.isNotEmpty(checked )){
                question.setChecked(Boolean.parseBoolean(checked));
            }else{
                anyNotChecked = true;
            }
        }
        return anyNotChecked;
    }

    @Override
    @Transactional
    public EvaluateV2Item nextEvaluateItem(String evaluateRecordId, String[] questionIds, boolean[] checkeds, boolean resume) {
        EvaluateV2Item item = nextEvaluatePlainItem(evaluateRecordId, questionIds, checkeds, resume);

        if(item != null) {
            if(item.getQuestions() == null){
                //从redis恢复的时候可能为空
                List<EvaluateV2Question> questions = questionRepository.findAllByItemIdAndDeletedIsFalseOrderByIndexOnPaper(item.getId());
                item.setQuestions(questions);
            }

            if(item.getQuestions().size() > 2){
                throw new BusinessException(ErrorCode.UNDEFINED, "缓存错误");
            }

            List<EvaluateV2Question> questions = item.getQuestions();
            if(questions != null) {
                //看看question是不是有关联选项
                for (EvaluateV2Question question : questions) {
                    if (question.getOptionGroup() != null && question.getOptionGroup() > 0) {
                        List<EvaluateV2Question> optionQuestions = questionRepository.findAllByOptionGroupAndIndexOnPaperGreaterThanEqualAndDeletedIsFalseOrderByIndexOnPaper(question.getOptionGroup(), question.getIndexOnPaper());

                        if (optionQuestions != null && optionQuestions.size() > 1) {
                            List options = optionQuestions.stream().map(q -> toOption(q)).collect(Collectors.toList());
                            question.setOptions(options);
                        }
                    }
                }
            }

        }

        return item;
    }
    private Map toOption(EvaluateV2Question q){
        //TODO:
        Map option = new HashMap();

        option.put("id", q.getId());
        option.put("optionTitle", q.getOptionTitle());
        option.put("indexOnPaper", q.getIndexOnPaper());

        return option;

    };

    public EvaluateV2Item nextEvaluatePlainItem(String evaluateRecordId, String[] questionIds, boolean[] checkeds, boolean resume) {
        EvaluateV2Record record = recordRepository.getOne(evaluateRecordId);

        if(record == null){
            throw new BusinessException(EVALUATE_RECORD_NOT_EXIST, "不存在的测评记录");
        }

        //测评的宝宝
        Children c = evaluateChildren(record);

        //月龄
        double actualMonth = DateUtil.betweenMonthsV2(record.getEvaluatingDate(), record.getBirthday());

        //需要测评的维度
        EvaluateV2Dimension dimension = null;

        //需要测评的Item
        EvaluateV2Item evaluateItem = null;

        //测评维度得分
        EvaluateV2RecordDimensionScore dimensionScore = null;

        //恢复任务
        if(resume){
            Object[] data = resumeAnswerData(evaluateRecordId);
            questionIds = (String[]) data[0];
            checkeds = (boolean[]) data[1];
        }

        if(questionIds == null || questionIds.length == 0 || checkeds == null || checkeds.length == 0){
            //没有提交答案时，移除所有的维度得分和答案重新开始测评
            List<EvaluateV2RecordAnswer> answers = answerRepository.findAllByRecordId(evaluateRecordId);
            if(answers != null && answers.size() > 0){
                //除答案缓存
                redisService.deleteLike(record.getId());
                //删除
                answerRepository.deleteAll(answers);
            }

            List<EvaluateV2RecordDimensionScore> dimensionScores = dimensionScoreRepository.findAllByRecordIdOrderByCreated(evaluateRecordId);
            dimensionScoreRepository.deleteAll(dimensionScores);

            //找到第一个维度
            if(StringUtils.isNotEmpty(record.getSkipDiemnsions())) {
                String[] comps = record.getSkipDiemnsions().split("\\|");
                List<String> skipIds = Lists.newArrayList(comps);
                dimension = dimensionRepository.findFirstByDeletedIsFalseAndIdNotInOrderByCode(skipIds);
            }else{
                dimension = dimensionRepository.findFirstByDeletedOrderByCode(false);
            }
            //找到缺省item
            evaluateItem = defaultItem(dimension.getId(), actualMonth, record.getDemoType());
            evaluateItem.setDimensionCode(dimension.getCode());

            //创建维度得分对象
            dimensionScore = defaultDimensionScore(record.getId(), evaluateItem, dimension, actualMonth );
        }else{
            //当前测评item
            String qid = questionIds[0];
            EvaluateV2Question q = questionRepository.getOne(qid);
            EvaluateV2Item curItem = q.getItem(); //itemRepository.getOne(q.getItemId());
            if(curItem == null){
                curItem = itemRepository.getOneByQuestionId(q.getId());
            }

            //当前测评维度
            String dimensionId = curItem.getDimensionId();
            dimension = dimensionRepository.getOne(dimensionId);

            double ppq =(curItem.getScore()+ 0.0) / (curItem.getQuestionCount() + 0.0) * 10;
            int pointPerQuestion = (int)ppq;

            //维度得分
            dimensionScore = dimensionScoreRepository.findOneByRecordIdAndDimensionId(record.getId(), dimensionId);

            //保存答案
            // 如果恢复的话，不用重新保存数据
            if(dimensionScore.getFinished()) {
                evaluateItem = null;
            }else{
                evaluateItem = saveQuestions(resume, questionIds, checkeds, curItem.getMonth(), pointPerQuestion, c, record, dimensionScore, dimension, curItem);

                //demo type =1 时，不继续了
                if (record.getDemoType() == 1){
                    evaluateItem = null;
                }

                //继续下一题
                if(evaluateItem != null) {
                    evaluateItem.setDimensionCode(dimension.getCode());
                    return evaluateItem;
                }

                //所有题目都没有通过  或者 测评表已经没有下一道题
                //维度标记为完成
                dimensionScore.setFinished(true);
                dimensionScoreRepository.save(dimensionScore);
            }

            //进入下一个维度
            EvaluateV2Dimension lastDimension = dimension;
            List<EvaluateV2Dimension> ds = null;
            if(StringUtils.isNotEmpty(record.getSkipDiemnsions())) {
                String[] comps = record.getSkipDiemnsions().split("\\|");
                List<String> skipIds = Lists.newArrayList(comps);
                ds = dimensionRepository.findDimensionAfterIdAndIdNotIn(dimensionId, skipIds);
            }else {
                ds = dimensionRepository.findDimensionAfterId(dimensionId);
            }
            if(ds == null || ds.size() == 0){
                dimension = null;
            }else{
                dimension = ds.get(0);
            }

            if(dimension == null){
                //把跳过的维度也创建得分,0分
                if(StringUtils.isNotEmpty(record.getSkipDiemnsions())){
                    String[] comps = record.getSkipDiemnsions().split("\\|");
                    for (String skipped_did : comps){
                        EvaluateV2Dimension d = dimensionRepository.getOne(skipped_did);
                        defaultDimensionScore(record.getId(), null, d, actualMonth );
                    }
                }

                //所有维度用完了, 标记测评完成
                record.setFinished(true);

                // 当前维度如果是心理行为测评， 重新计算心理行为测评月龄
                // 宝宝月龄 -  心理行为月龄
                // 若小于零， 则为0
                if(WARNING_DIMENSION_ID.equals(lastDimension.getId()) && dimensionScore != null && WARNING_DIMENSION_ID.equals(dimensionScore.getDimensionId())){
                    resetWarningDimensionScore(dimensionScore, actualMonth);
                    dimensionScoreRepository.save(dimensionScore);
                }

                //FIXME 这里需要处理, 等到pc可以发布了，就可以不用处理这个字段。
                record.setStatus(2);
                recordRepository.save(record);
            }else {
                dimensionId = dimension.getId();

                evaluateItem = defaultItem(dimensionId, actualMonth, record.getDemoType());
                evaluateItem.setDimensionCode(dimension.getCode());

                //创建维度得分对象
                dimensionScore = defaultDimensionScore(record.getId(), evaluateItem, dimension, actualMonth );
            }
        }

        return evaluateItem;
    }

    private void resetWarningDimensionScore(EvaluateV2RecordDimensionScore score, double actualMonth){
        int new_warning_score = (int)(actualMonth * 10 - score.getScore());
        if(new_warning_score < 0){
            new_warning_score = 0;
        }
        log.info("reset warning_dimension_score from " + score.getDq() + " to " + new_warning_score + " for children " + score.getId());
        score.setMonth(new_warning_score);
        score.setDq(score.getScore());
    }

    @Override
    public List<EvaluateV2ItemVO> fullEvaluateItems(String dimensionId, Date birthday){
        List<EvaluateV2Item> items = null;
        if (StringUtils.isNotEmpty(dimensionId)) {
            items = itemRepository.findAllByDimensionIdOrderByMonth(dimensionId);
        }else {
            items = itemRepository.findAllByOrderByDimensionCodeAscMonthAsc();
        }

        Map<String, List<EvaluateV2QuestionVO>> questionCache = new HashMap<>();
        List<EvaluateV2Question> fullQuestions = questionRepository.findAll();
        for (EvaluateV2Question question : fullQuestions){
            List<EvaluateV2QuestionVO> itemQuestions = questionCache.get(question.getItemId());
            if (itemQuestions == null){
                itemQuestions = new ArrayList<>(2);
                questionCache.put(question.getItemId(), itemQuestions);
            }
            itemQuestions.add(EvaluateV2QuestionVO.ofWithoutTools(question));
        }

        List<EvaluateV2ItemVO> results = items.stream().map(k->EvaluateV2ItemVO.of(k, questionCache.get(k.getId()))).collect(Collectors.toList());

        //
        double actualMonth = DateUtil.betweenMonthsV2(new Date(), birthday);
        int month = (int)actualMonth;

        //找到合适的
        EvaluateV2ItemVO last = null;
        for (EvaluateV2ItemVO item : results){
            if (last != null && !last.getDimensionId().equals(item.getDimensionId())){
                last = null;
            }

//            if (item.getDimensionId().equals(WARNING_DIMENSION_ID)){
//                //心理警示行为
//                if (last == null) {
//                    item.setBeginAt(true);
//                }
//
//                last = item;
//
//            }else
            {
                //其他能区
                if (last == null || item.getMonth() <= month ){
                    last = item;
                }

                if (item.getMonth() > month){
                    //last 赋值并清空
                    if (last != null){
                        last.setBeginAt(true);
                    }

                    continue;
                }
            }
        }

        return results;
    }

    private Children evaluateChildren(EvaluateV2Record record){
        Children c = null;
        if(StringUtils.isEmpty(record.getChildrenId())){
            c = new Children();
            c.setId(record.getId());
            c.setName(record.getChildrenName());
            c.setNickName(record.getChildrenNickName());
            c.setBirthday(record.getBirthday());
        }else {
            c = childrenRepository.getOne(record.getChildrenId());
        }
        return c;
    }

    private Object[] resumeAnswerData(String evaluateRecordId){
        String questionIds[] = null;
        boolean checkeds[] = null;
        List<EvaluateV2RecordAnswer> answers = answerRepository.findAllByRecordIdOrderByCreatedDesc(evaluateRecordId);
        if(answers != null && answers.size() > 0){
            Integer qm = answers.get(0).getMonth();
            String[] qIds = answers.stream().filter(k->k.getMonth()==qm).map(k->k.getQuestionId()).toArray(String[]::new);
            Boolean[] cs = answers.stream().filter(k->k.getMonth()==qm).map(k->k.isChecked()).toArray(Boolean[]::new);

            questionIds = qIds;
            checkeds = new boolean[cs.length];
            for (int i = 0; i < cs.length; i++){
                checkeds[i] = cs[i] != null ? cs[i] : false;
            }
        }

        return new Object[]{questionIds, checkeds};
    }

    private EvaluateV2Item saveQuestions( boolean resume,
                                          String[] questionIds, boolean[] checkeds, Integer month, int pointPerQuestion,
                                          Children c, EvaluateV2Record record, EvaluateV2RecordDimensionScore dimensionScore,
                                          EvaluateV2Dimension dimension, EvaluateV2Item curItem){


        Double actualMonth = DateUtil.betweenMonthsV2(new Date(), c.getBirthday());

        boolean scoreChanged = false;
        boolean anyChecked = false;
        boolean allChecked = true;

        for (int i = 0; i < questionIds.length; i++) {
            String questionId = questionIds[i];
            boolean checked = checkeds[i];

            if(!resume) {
                // 恢复时不保存答案，直接
                EvaluateV2Question question = questionRepository.getOne(questionId);
                if(!checked) {
                    //把关联问题一并标记为不通过
                    //mark shortQuestions unpassed
                    markShortItemsUnpassed(record.getId(), question);
                }

                EvaluateV2RecordAnswer answer = answerRepository.findTopByQuestionIdAndChildrenIdAndRecordId(questionId, c.getId(), record.getId());
                if (answer != null) {
                    answer.set(dimensionScore.getId(), month, question.getTitle(), checked, checked ? pointPerQuestion : 0);
                } else {
                    answer = EvaluateV2RecordAnswer.of(questionId, c.getId(), record.getId(), dimensionScore.getId(), month, question.getTitle(), checked, checked ? pointPerQuestion : 0);
                }

                answerRepository.save(answer);

                //计算维度得分
                dimensionScore.setScore(dimensionScore.getScore() + answer.getScore());
                //新的得分计算
                dimensionScore.setMonth(dimensionScore.getMonth() + answer.getScore());
                //计算发育商
                dimensionScore.setDq((int)(dimensionScore.getMonth() * 1.0 / actualMonth * 100 /*100%*/));

                scoreChanged = true;
            }

            anyChecked |= checked;
            allChecked &= checked;
        }

        if(!resume) {
            //全部通过时修正分数，前面单个不通过的题目作废
//            if (allChecked && dimension.getDefaultValueType() != 1 /*警示行为*/) {
//                //如果全通过，直接根据月龄计算得分
//                dimensionScore.setScore(curItem.getMonth() * 10);
//                //新的得分计算
//                dimensionScore.setMonth(curItem.getMonth() * 10);
//                //计算发育商
//                dimensionScore.setDq((int)(dimensionScore.getMonth() * 1.0 / actualMonth * 100 /*100%*/));
//
//                scoreChanged = true;
//            }

            if (!anyChecked ) {
                //&& dimensionScore.getUnpassCount() == 0
                //连续两次未结束才下一个维度
                dimensionScore.setUnpassCount(dimensionScore.getUnpassCount() + 1);
                scoreChanged = true;

                anyChecked = true;
            } else if (anyChecked && dimensionScore.getUnpassCount() != 0) {
                dimensionScore.setUnpassCount(0);
                scoreChanged = true;
            }
        }

        if(scoreChanged) {
            dimensionScoreRepository.save(dimensionScore);
        }

        //下一个item
        EvaluateV2Item evaluateItem = null;

        if (dimensionScore.getUnpassCount() < 2) {
            //if (anyChecked || (resume && dimensionScore.getUnpassCount() == 1 && !dimensionScore.getFinished() /*just for read*/)) {
            //找到下一个测评Item
            evaluateItem = itemRepository.findFirstByDimensionIdAndMonthGreaterThanAndDeletedOrderByMonth(dimension.getId(), curItem.getMonth(), false);

            if(evaluateItem != null && evaluateItem.getQuestions() != null && evaluateItem.getQuestions().size() > 2){
                throw new BusinessException(ErrorCode.UNDEFINED, "缓存错误");
            }

            if (dimensionScore.getUnpassCount() == 0 && !allChecked && dimension != null && evaluateItem != null) {
                //出未来两个题的题目数总和
                //TODO, 更新失败计数器
                List<EvaluateV2Item> items = itemRepository.findTop2ByDimensionIdAndMonthGreaterThanAndDeletedIsFalseOrderByMonth(dimension.getId(), evaluateItem.getMonth());
                for (EvaluateV2Item item : items){
                    if(evaluateItem.getRestUnpassToNextDimension() == null){
                        evaluateItem.setRestUnpassToNextDimension(evaluateItem.getRestUnpassToNextDimension());
                    }else {
                        evaluateItem.setRestUnpassToNextDimension(item.getQuestionCount() + evaluateItem.getRestUnpassToNextDimension());
                    }
                }

            }else if (dimensionScore.getUnpassCount() ==  1 && evaluateItem != null){
                evaluateItem.setRestUnpassToNextDimension(evaluateItem.getQuestionCount());
            }
        }

        return evaluateItem;
    }

    @Override
    public List<EvaluateV2Dimension> allValidEvaluatedDimension(boolean skipWarningDiemension) {
        if (skipWarningDiemension){
            return dimensionRepository.findAllByIdNotAndDeletedIsFalseOrderByCode(WARNING_DIMENSION_ID);
        }
        return dimensionRepository.findAllByDeletedOrderByCode(false);
    }

    @Override
    public List<Integer> allValidMonthList(String dimensionId) {

        Integer[] result = {
                1,	2,	3,	4,	5,	6,	7,	8,
                9,	10,	11,	12,	15,	18,	21,	24,
                27,	30,	33,	36,	42,	48,	54,	60,
                66,	72,	78,	84
        };
        return Arrays.asList(result);
    }

    @Override
    public EvaluateV2Question getQuestionDetail(String questionId) {
        return questionRepository.getOne(questionId);
    }

    @Override
    public EvaluateV2Record getLastEvaluateRecord(String childrenId) {
        EvaluateV2Record record =  recordRepository.findFirstByChildrenIdAndFinishedIsTrueOrderByCreatedDesc(childrenId);

        if(record == null){
            return null;
        }

        List<EvaluateV2RecordDimensionScore> dimensionScores = dimensionScoreRepository.findAllByRecordIdOrderByCreated(record.getId());
        record.setDimensionScores(dimensionScores);

        return record;
    }

    @Override
    public EvaluateV2Record getEvaluateDetail(String evaluateId) {
        return getEvaluateDetailByIdAndStaffId(evaluateId, null, true, null);
    }

    public EvaluateV2Record getEvaluateDetail(String evaluateId, String recommendChannel) {
        return getEvaluateDetailByIdAndStaffId(evaluateId, null, true, recommendChannel);
    }

    @Override
    public EvaluateV2Record getEvaluateDetailForStaff(String evaluateId, String staffId){
        return getEvaluateDetailForStaff(evaluateId, staffId, true);
    }

    @Override
    public EvaluateV2Record getEvaluateDetailForStaff(String evaluateId, String staffId, String recommendChannel){
        return getEvaluateDetailForStaff(evaluateId, staffId, true, recommendChannel);
    }

    @Override
    public EvaluateV2Record getEvaluateDetail(String evaluateId,  boolean withHightLevelInfo){
        return getEvaluateDetailByIdAndStaffId(evaluateId, null, withHightLevelInfo, null);
    }

    @Override
    public EvaluateV2Record getEvaluateDetailForStaff(String evaluateId, String staffId, boolean withHightLevelInfo){
        return getEvaluateDetailForStaff(evaluateId, staffId, withHightLevelInfo, null);
    }

    @Override
    public EvaluateV2Record getEvaluateDetailForStaff(String evaluateId, String staffId, boolean withHightLevelInfo, String recommendChannel){
        if(StringUtils.isBlank(staffId)){
            throw new BusinessException(ErrorCode.STAFF_NOT_EXIST, "staffId错误");
        }

        return getEvaluateDetailByIdAndStaffId(evaluateId, staffId, withHightLevelInfo, recommendChannel);
    }

    private EvaluateV2Record getEvaluateDetailByIdAndStaffId(String evaluateId, String staffId, boolean withHightLevelInfo, String recommendChannel){
        EvaluateV2Record record = null;

        if(staffId == null){
            record = recordRepository.getOne(evaluateId);
        }else {
            record = recordRepository.getByIdAndCreateTeacherId(evaluateId, staffId);
        }

        if(record == null){
            throw new BusinessException(EVALUATE_RECORD_NOT_EXIST, "没有测评记录");
        }

        List<EvaluateV2RecordDimensionScore> dimensionScores = dimensionScoreRepository.findAllByRecordIdOrderByCreated(evaluateId);
        record.setDimensionScores(dimensionScores);

        //缓存维度
        if(withHightLevelInfo) {
            List<EvaluateV2Dimension> dimensions = dimensionRepository.findAllByDeletedOrderByCode(false);
            HashMap<String, EvaluateV2Dimension> mapping = new HashMap<>();
            dimensions.stream().forEach(p -> {
                mapping.put(p.getId(), p);
            });

            List<EvaluateV2Item> failedQuestionItems = itemRepository.findAllFailedQuestionItems(record.getId());
            if (failedQuestionItems != null && failedQuestionItems.size() > 0) {
                List<EvaluateV2ExtInfoVO> highLevelInfo = failedQuestionItems.stream()
                        .map(i -> EvaluateV2ExtInfoVO.of(i, mapping.get(i.getDimensionId())))
                        .collect(Collectors.toList());
                record.setHighLevelInfo(highLevelInfo);
            }

            if (StringUtils.isNotEmpty(recommendChannel)){
                //查询
                List<EvaluateV2ExtInfoVO> highLevelInfo = record.getHighLevelInfo();
                if (highLevelInfo != null && highLevelInfo.size() > 0){
                    for (EvaluateV2ExtInfoVO extInfo : highLevelInfo){
                        EvaluateV2DimensionRecommendTips tips =
                                tipsRepository.getFirstByChannelOrChannelIsNull(extInfo.getDimensionId(), extInfo.getMonth(), recommendChannel);
                        if (tips != null && StringUtils.isNotEmpty(tips.getUrl())) {
                            extInfo.setRecommendURL(tips.getUrl());
                            extInfo.setRecommendTips(null);
                        }
                    }
                }
            }
        }

        return record;
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public boolean grantEvaluateToParent(StaffDTO sourceTeacher, EvaluateV2Record record){
//        Children children = childrenService.getById(record.getChildrenId());
//
//        if (StringUtils.isEmpty(children.getExtendInfo().getGuardianPhone())){
//            throw new BusinessException(ErrorCode.PARENT_PHONE_NEEDED, "没有填写家长联系方式");
//        }
//
//        List<Staff> staffs = staffService.getByPhone(children.getExtendInfo().getGuardianPhone(), null, CommonConstant.Platform.WXMP.codeOf());
//
//        String title = children.getName() + "的心理行为测评报告";
//
//        if(staffs.size() > 0) {
//            List<Feeds> newFeeds = staffs.stream().map(k -> {
//                        Feeds ret = Feeds.of(
//                                title,
//                                sourceTeacher,
//                                staffService.staffOrgnization(sourceTeacher),
//                                record.getChildrenId(), record.getChildrenName(), record.getGender(),
//                                FeedsService.FeedsType.EvaluateRecord,
//                                k.getId(),
//                                record.getId(),
//                                record.getCreated()
//                        );
//                        return ret;
//                    }).collect(Collectors.toList());
//            feedsRepository.saveAll(newFeeds);
//
//            //推送消息
//            String guardianPhone = children.getExtendInfo().getGuardianPhone();
//            if (StringUtils.isNotEmpty(guardianPhone)){
//                List<Staff> parents = staffService.getByPhone(guardianPhone, null, CommonConstant.Platform.WXMP.codeOf());
//                parents.stream().filter(k->StringUtils.isNotEmpty(k.getOpenidMP())).forEach(k->{
//                    pushService.pushToParentsWithEvaluateRecord(k, record);
//                });
//            }
//        }
//
//        record.setParentGranted(true);
//        recordRepository.save(record);

        return true;
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public boolean revokeGrantEvaluateToParent(String staffId, EvaluateV2Record record){
        record.setParentGranted(false);
        recordRepository.save(record);
        feedsRepository.deleteAllByRecordId(record.getId());
        return true;
    }

    @Override
    public void notifyParentToEvaluate(String staffId, String childrenId){
//        Children c = childrenService.getById(childrenId, staffId);
//
//        if (c == null){
//            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在");
//        }
//
//        String guardianPhone = c.getExtendInfo().getGuardianPhone();
//        if (StringUtils.isEmpty(guardianPhone)){
//            throw new BusinessException(ErrorCode.PARENT_PHONE_NEEDED, "没有填写家长手机号码");
//        }
//
//        List<Staff> parents = staffService.getByPhone(guardianPhone, null, CommonConstant.Platform.WXMP.codeOf());

    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public boolean grantAllEvaluateToParent(StaffDTO parent){

        //删除children关联的feed
        //feedsRepository.deleteAllByFeedsUserIdAndFeedType(parent.getId(), FeedsService.FeedsType.EvaluateRecord.getType());

        if (StringUtils.isEmpty(parent.getMobile())){
            return true;
        }

        List<Children> childrenList = childrenRepository.findAllByParentPhoneAndDeletedIsFalse(parent.getMobile());

        List<String> childrenIds = childrenList.stream().map(k->k.getId()).collect(Collectors.toList());
        List<EvaluateV2Record> records = recordRepository.findAllByChildrenIdInAndParentGrantedIsTrue(childrenIds);

        //重新创建所有children关联的feed

        //TODO   推送
//        List<Feeds> feeds = records.stream().map( k -> {
//            StaffDTO sourceTeacher = staffService.getById(k.getCreateTeacherId());
//            Organization org = staffService.staffOrgnization(sourceTeacher);
//            return Feeds.of(
//                    k.getChildrenName() + "的心理行为测评报告",
//                    sourceTeacher,
//                    org,
//                    k.getChildrenId(),
//                    k.getChildrenName(),
//                    k.getGender(),
//                    FeedsService.FeedsType.EvaluateRecord,
//                    parent.getId(),
//                    k.getId(), k.getCreated());
//        }).collect(Collectors.toList());
//
//        feedsRepository.saveAll(feeds);

        return true;
    }

    @Override
    public boolean deleteReportForStaff(String evaluateId, String staffId){
        EvaluateV2Record record = recordRepository.getByIdAndCreateTeacherId(evaluateId, staffId);
        if(record == null){
            throw  new BusinessException(EVALUATE_RECORD_NOT_EXIST, "报告不存在");
        }

        record.setDeleted(true);

        recordRepository.save(record);

        return true;
    }

    @Override
    public List<EvaluateV2Tool> getEvaluateToolsForQuestion(String questionId){
        return toolRepository.findAllByQuestionIdAndDeletedIsFalse(questionId);
    }

    @Override
    public List<EvaluateV2Tool> getEvaluateToolsForItem(String itemId){
        return toolRepository.findAllByItemIdAndDeletedIsFalse(itemId);
    }

    @Override
    public List<EvaluateV2ToolVO> getFullEvaluateTools(Integer month){

        if (month != null) {
            List<EvaluateV2Item> top2 = itemRepository.findTop2ByDimensionIdAndMonthLessThanAndDeletedOrderByMonthDesc(WARNING_DIMENSION_ID, month, false);

            if (top2 == null || top2.size() == 0) {
                month = null;
            } else {
                EvaluateV2Item prevItem = top2.get(0);
                month = prevItem.getMonth();
            }
        }

        return toolNativeRepository.findAllTools(month);
    }

//    @Override
//    public boolean transferReports(StaffDTO sourceStaff, StaffDTO targetStaff){
//
//        Organization org = evaluateStaffService.staffOrgnization(targetStaff);
//
//        recordRepository.updateAllReportsFromTo(sourceStaff.getId(), targetStaff.getId(), org.getId());
//
//        return true;
//    }

    @Override
    public Integer countReportsByStaffIds(List<String> ids, Date date){
        if (date != null){
            return recordRepository.countAllByCreateTeacherIdInAndCreatedGreaterThanAndFinishedIsTrue(ids, date);
        }else{
            return recordRepository.countAllByCreateTeacherIdInAndFinishedIsTrue(ids);
        }
    }

}
